package com.ruoyi.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
import com.huifu.bspay.sdk.opps.core.utils.RsaUtils;
import com.ruoyi.common.config.HfuPayConfig;
import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.common.core.domain.dto.RoleDTO;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.common.utils.HfuPayUtils;
import com.ruoyi.common.utils.JsonUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.common.utils.TimeUtil;
import com.ruoyi.common.utils.redis.RedisUtils;
import com.ruoyi.common.vo.HfuPayResultVo;
import com.ruoyi.system.alipay.AlipayConstants;
import com.ruoyi.system.alipay.AlipayTradeWapPayUtils;
import com.ruoyi.system.constants.DyRoleKeyConstants;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.domain.bo.DyIndexBo;
import com.ruoyi.system.domain.bo.DyOrderGoodsBo;
import com.ruoyi.system.domain.vo.*;
import com.ruoyi.system.enums.OrderStatusEnum;
import com.ruoyi.system.mapper.*;
import com.ruoyi.system.service.IDyCommonService;
import com.ruoyi.system.vo.AlipayResultVo;
import com.ruoyi.system.vo.HfuOrderResultVo;
import com.ruoyi.system.vo.HfuPayResultJsonVo;
import com.ruoyi.system.vo.HfuPayResultJsonWxVo;
import io.swagger.v3.core.util.Json;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import com.ruoyi.system.domain.bo.DyOrderBo;
import com.ruoyi.system.service.IDyOrderService;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 订单Service业务层处理
 *
 * @author ruoyi
 * @date 2024-06-20
 */
@RequiredArgsConstructor
@Service
@Slf4j
@Transactional(rollbackFor = Exception.class)
public class DyOrderServiceImpl implements IDyOrderService {

    private final DyOrderMapper baseMapper;

    private final DyAnchorMapper dyAnchorMapper;

    private final DyGoodsMapper dyGoodsMapper;

    private final SysDeptMapper sysDeptMapper;

    private final DyRemitRecordMapper dyRemitRecordMapper;

    private final DyMemberCodeMapper dyMemberCodeMapper;

    private final DyClientAnchorMapper dyClientAnchorMapper;

    private final DyClientMapper dyClientMapper;

    private final DyAnchorPhotoMapper dyAnchorPhotoMapper;

    private static final String DAY_ORDER_PRE_KEY = "day_order_pre";

    @Resource
    private IDyCommonService iDyCommonService;
    private final IdentifierGenerator identifierGenerator;

    /**
     * 查询订单
     */
    @Override
    public DyOrderVo queryById(Long id){
        return baseMapper.selectVoById(id);
    }

    /**
     * 查询订单列表
     */
    @Override
    public TableDataInfo<DyOrderVo> queryPageList(DyOrderBo bo, PageQuery pageQuery, LoginUser loginUser) {

        RoleDTO roleDTO = iDyCommonService.getFirstRole(loginUser.getRoles());

        if (ObjectUtil.isEmpty(roleDTO)){
            throw new ServiceException("无数据查看权限");
        }

        LambdaQueryWrapper<DyOrder> lqw = buildQueryWrapper(bo);

        List<DyAnchor> anchors = new ArrayList<>();

        List<String> roleKeys = loginUser.getRoles().stream().map(RoleDTO::getRoleKey).collect(Collectors.toList());

        //分公司管理员
        if (CollUtil.contains(roleKeys, DyRoleKeyConstants.roleKeySubCompany)){

            List<DyAnchor> roleKeySubCompany = dyAnchorMapper.selectList(new QueryWrapper<DyAnchor>().lambda()
                    .eq(bo.getAnchorId() != null, DyAnchor::getId, bo.getAnchorId())
                    .in(roleDTO.getRoleKey().equals(DyRoleKeyConstants.roleKeySubCompany), DyAnchor::getCompanyId, loginUser.getDeptId()));

            anchors = (List<DyAnchor>) CollUtil.union(anchors, roleKeySubCompany);
        }

//        if (CollUtil.contains(roleKeys, DyRoleKeyConstants.roleKeyCustomerService)){
//            List<DyAnchor> roleKeyCustomerService = dyAnchorMapper.selectList(new QueryWrapper<DyAnchor>().lambda()
//                    .in(roleDTO.getRoleKey().equals(DyRoleKeyConstants.roleKeyCustomerService), DyAnchor::getCustomerId, loginUser.getUserId())
//                    .eq(bo.getAnchorId() != null, DyAnchor::getId, bo.getAnchorId()));
//            anchors = (List<DyAnchor>) CollUtil.union(anchors, roleKeyCustomerService);
//        }

        if (CollUtil.contains(roleKeys, DyRoleKeyConstants.roleKeyAdmin) || CollUtil.contains(roleKeys, DyRoleKeyConstants.roleKeyCompanyAdmin) || CollUtil.contains(roleKeys, DyRoleKeyConstants.roleKeyCustomerService)){

            List<DyAnchor> dyAnchors = dyAnchorMapper.selectList(new QueryWrapper<DyAnchor>().lambda()
                    .eq(bo.getAnchorId() != null, DyAnchor::getId, bo.getAnchorId()));

            anchors = (List<DyAnchor>) CollUtil.union(anchors, dyAnchors);
        }
//
        if (anchors.isEmpty()){
            return TableDataInfo.build();
        }

        List<Long> acIds = anchors.stream().map(DyAnchor::getId).collect(Collectors.toList());

        lqw.eq(bo.getOrderStatus() != null, DyOrder::getOrderStatus, bo.getOrderStatus());
        lqw.eq(StringUtils.isNotEmpty(bo.getOrderNo()), DyOrder::getOrderNo, bo.getOrderNo());
        lqw.eq(StringUtils.isNotEmpty(bo.getTradeNo()), DyOrder::getTradeNo, bo.getTradeNo());

        lqw.between(bo.getStartTime() != null,BaseEntity::getUpdateTime,bo.getStartTime(),bo.getEndTime());

        lqw.in(DyOrder::getAnchorId, acIds);
        lqw.orderByDesc(DyOrder::getUpdateTime);
        Page<DyOrderVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);

        for (DyOrderVo record : result.getRecords()) {
            record.setAnchorName(record.getGoodsName());
            if (StringUtils.isNotEmpty(record.getToken())){
                DyMemberCode code = dyMemberCodeMapper.selectOne(new QueryWrapper<DyMemberCode>().lambda().eq(DyMemberCode::getToken, record.getToken()));
                if (code != null){
                    record.setIsUse(code.getStatus() != 0);
                }
            }
        }

        return TableDataInfo.build(result);
    }

    /**
     * 查询订单列表
     */
    @Override
    public List<DyOrderVo> queryList(DyOrderBo bo) {
        LambdaQueryWrapper<DyOrder> lqw = buildQueryWrapper(bo);
        List<DyOrderVo> result = baseMapper.selectVoList(lqw);
        if (CollectionUtil.isNotEmpty(result)){
            List<Long> authorIds = result.stream().map(DyOrderVo::getAnchorId).collect(Collectors.toList());
            List<DyAnchorVo> anchorVos = dyAnchorMapper.selectVoBatchIds(authorIds);
            Map<Long,DyAnchorVo> anchorMap = new HashMap<>();
            if (CollectionUtil.isNotEmpty(anchorVos)){
                anchorMap = anchorVos.stream().collect(Collectors.toMap(DyAnchorVo::getId,item -> item,(k1,k2) -> k1));
            }
            for (DyOrderVo item : result){
                if (ObjectUtil.isNotEmpty(anchorMap.get(item.getAnchorId())) && ObjectUtil.isNotEmpty(anchorMap.get(item.getAnchorId()).getName())){
                    item.setAnchorName(anchorMap.get(item.getAnchorId()).getName());
                }
            }
        }
        return result;
    }

    private LambdaQueryWrapper<DyOrder> buildQueryWrapper(DyOrderBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<DyOrder> lqw = Wrappers.lambdaQuery();
        lqw.like(StringUtils.isNotBlank(bo.getOrderNo()), DyOrder::getOrderNo, bo.getOrderNo());
        lqw.eq(bo.getAnchorId() != null, DyOrder::getAnchorId, bo.getAnchorId());
        lqw.eq(bo.getAmount() != null, DyOrder::getAmount, bo.getAmount());
        lqw.eq(bo.getType() != null, DyOrder::getType, bo.getType());
        lqw.eq(bo.getOrderStatus() != null, DyOrder::getOrderStatus, bo.getOrderStatus());
        return lqw;
    }

    /**
     * 新增订单
     */
    @Override
    public Boolean insertByBo(DyOrderBo bo) {
        DyOrder add = BeanUtil.toBean(bo, DyOrder.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改订单
     */
    @Override
    public Boolean updateByBo(DyOrderBo bo) {
        DyOrder update = BeanUtil.toBean(bo, DyOrder.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    @Override
    public DyOrderSumVo getOrderSum(DyOrderBo bo, LoginUser loginUser) {

        RoleDTO roleDTO = iDyCommonService.getFirstRole(loginUser.getRoles());
        if (ObjectUtil.isEmpty(roleDTO)){
            throw new ServiceException("无数据查看权限");
        }

        LocalDate toDate = LocalDate.now();

        DyOrderSumVo result = new DyOrderSumVo();
        LambdaQueryWrapper<DyOrder> queryWrapperYesToday = new LambdaQueryWrapper<>();
        queryWrapperYesToday.between(BaseEntity::getUpdateTime, TimeUtil.getMonthFirstDay(toDate.minusMonths(1).atStartOfDay()), TimeUtil.getMonthFirstDay(toDate.plusMonths(1).atStartOfDay()));
        queryWrapperYesToday.eq(bo.getOrderStatus() != null, DyOrder::getOrderStatus, bo.getOrderStatus());
        queryWrapperYesToday.eq(bo.getAnchorId() != null, DyOrder::getAnchorId, bo.getAnchorId());
        queryWrapperYesToday.like(StringUtils.isNotEmpty(bo.getOrderNo()), DyOrder::getOrderNo, bo.getOrderNo());
        List<DyOrderVo> orderVos = baseMapper.selectVoList(queryWrapperYesToday);

        if (CollectionUtil.isNotEmpty(orderVos)){

            log.info("getOrderSum获取昨日订单信息");
            List<DyOrderVo> orderVosYesToday = orderVos.stream().filter(f -> f.getUpdateTime().after(TimeUtil.localDateTimeToDate(toDate.minusDays(1).atStartOfDay()))
                    && f.getUpdateTime().before(TimeUtil.localDateTimeToDate(toDate.atStartOfDay()))).collect(Collectors.toList());

            result.setYesterdayOrderNum(orderVosYesToday.size());
            Integer orderVosYesTodayAmount = orderVosYesToday.stream().mapToInt(DyOrderVo::getAmount).sum();
            result.setYesterdayOrderAmount(orderVosYesTodayAmount);

            log.info("getOrderSum获取今日订单信息");
            List<DyOrderVo> orderVosToday = orderVos.stream().filter(f -> f.getUpdateTime().after(TimeUtil.localDateTimeToDate(toDate.atStartOfDay()))
                    && f.getUpdateTime().before(TimeUtil.localDateTimeToDate(toDate.plusDays(1).atStartOfDay()))).collect(Collectors.toList());

            result.setTodayOrderNum(orderVosToday.size());
            Integer orderVosTodayAmount = orderVosToday.stream().mapToInt(DyOrderVo::getAmount).sum();
            result.setTodayOrderAmount(orderVosTodayAmount);

            log.info("getOrderSum获取上月订单信息");
            List<DyOrderVo> orderVosPreMonth = orderVos.stream()
                    .filter(f -> f.getUpdateTime().after(TimeUtil.getMonthFirstDay(toDate.minusMonths(1).atStartOfDay()))
                    && f.getUpdateTime().before(TimeUtil.getMonthFirstDay(toDate.atStartOfDay()))).collect(Collectors.toList());

            result.setPreMonthOrderNum(orderVosPreMonth.size());
            Integer orderVosPreMonthAmount = orderVosPreMonth.stream().mapToInt(DyOrderVo::getAmount).sum();
            result.setPreMonthOrderAmount(orderVosPreMonthAmount);

            log.info("getOrderSum获取本月订单信息");
            List<DyOrderVo> orderVosMonth = orderVos.stream().filter(f -> f.getUpdateTime().after(TimeUtil.getMonthFirstDay(toDate.atStartOfDay()))
                    && f.getUpdateTime().before(TimeUtil.getMonthFirstDay(toDate.plusMonths(1).atStartOfDay()))).collect(Collectors.toList());

            result.setMonthOrderNum(orderVosMonth.size());
            Integer orderVosMonthAmount = orderVosMonth.stream().mapToInt(DyOrderVo::getAmount).sum();
            result.setMonthOrderAmount(orderVosMonthAmount);
        }

        return result;
    }

    @Override
    public List<OrderIndexIncomeSumVo> getIndexIncomeSum(LoginUser loginUser) {
        List<OrderIndexIncomeSumVo> result = new ArrayList<>();
        LocalDate today = LocalDate.now();
        Date startTime = TimeUtil.getTimeStartFrontDayIndex(15,today);
        Date endTimeNow = new Date();
        List<DyOrderVo> orderVosIndex = new ArrayList<>();

        //  如果是总公司
        if (loginUser.getDeptId() == 100){
            LambdaQueryWrapper<DyOrder> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.between(DyOrder::getUpdateTime, startTime, endTimeNow);
            queryWrapper.eq(DyOrder::getOrderStatus,OrderStatusEnum.PAID.getKey());
            orderVosIndex = baseMapper.selectVoList(queryWrapper);
        } else {
            LambdaQueryWrapper<DyAnchor> queryWrapperAnchor = new LambdaQueryWrapper<>();
            queryWrapperAnchor.eq(DyAnchor::getCompanyId, loginUser.getDeptId());
            List<DyAnchorVo> anchorVos = dyAnchorMapper.selectVoList(queryWrapperAnchor);

            if (CollectionUtil.isNotEmpty(anchorVos)){
                List<Long> anchorIds = anchorVos.stream().map(DyAnchorVo::getId).collect(Collectors.toList());
                LambdaQueryWrapper<DyOrder> queryWrapperOrder = new LambdaQueryWrapper<>();
                queryWrapperOrder.in(DyOrder::getAnchorId, anchorIds);
                queryWrapperOrder.eq(DyOrder::getOrderStatus, 1);
                orderVosIndex = baseMapper.selectVoList(queryWrapperOrder);
            }
        }

        Map<String,Integer> indexMap = new HashMap<>();
        if (CollectionUtil.isNotEmpty(orderVosIndex)){
            indexMap = orderVosIndex.stream().collect(Collectors.groupingBy(entity -> TimeUtil.dateToCalendar(entity.getUpdateTime()).get(Calendar.YEAR) + "_"
                            + TimeUtil.dateToCalendarMonth(entity.getUpdateTime()) + "_" + TimeUtil.dateToCalendar(entity.getUpdateTime()).get(Calendar.DAY_OF_MONTH),
                    Collectors.summingInt(DyOrderVo::getAmount)));
        }

        List<LocalDate> localDateList = TimeUtil.getTimeFrontDayListIndex(15,today);
        for(LocalDate item : localDateList){
            OrderIndexIncomeSumVo orderIndexIncomeSumVo = new OrderIndexIncomeSumVo();
            orderIndexIncomeSumVo.setDateTime(item);
            Integer year = item.getYear();
            int month = item.getMonthValue();
            int day = item.getDayOfMonth();
            String key = year + "_" + month + "_" + day;
            if (ObjectUtil.isNotEmpty(indexMap.get(key))){
                Integer amount = indexMap.get(key);
                orderIndexIncomeSumVo.setSum(amount);
            }
            result.add(orderIndexIncomeSumVo);
        }
        return result;
    }

    @Override
    public String addOrderPayDemoTest(DyOrderGoodsBo bo) {
        try {
            return AlipayTradeWapPayUtils.getTestDemo2();
        } catch (Exception e){
            throw new ServiceException(e.getMessage());
        }
    }

    /**
     * 创建订单
     * @param bo payType (0微信，1支付宝, 2汇付支付宝, 3汇付微信)
     * @return
     */
    @Override
    public synchronized String addOrderPay(DyOrderGoodsBo bo) {

        DyGoodsVo dyGoodsVo = dyGoodsMapper.selectVoById(bo.getGoodsId());

        if (ObjectUtil.isEmpty(dyGoodsVo)){
            throw new ServiceException("无效商品！");
        }

        DyAnchorVo dyAnchorVo = dyAnchorMapper.selectVoById(dyGoodsVo.getAnchorId());
        if (ObjectUtil.isEmpty(dyAnchorVo)){
            throw new ServiceException("无效主播！");
        }

        if (bo.getPayType() == null){
            throw new ServiceException("参数错误！");
        }

        String result = "";

        String orderNo = buildOrderNo();

        BigDecimal goodsAmount = BigDecimal.valueOf(dyGoodsVo.getAmount());
        BigDecimal per = BigDecimal.valueOf(100);
        BigDecimal totalAmount = goodsAmount.divide(per,2, RoundingMode.HALF_UP);

        // 生成订单
        DyOrder dyOrder = new DyOrder();
        dyOrder.setCreateBy("order");
        dyOrder.setUpdateBy("order");
        dyOrder.setType(bo.getPayType());
        dyOrder.setOrderStatus(0);
        dyOrder.setOrderType(0);

        if (bo.getPayType() == 0L) {
            //微信
            result = "ok";

            if (StringUtils.isEmpty(bo.getPayUrl()) || bo.getPayType() == null || StringUtils.isEmpty(bo.getTradeNo())){
                throw new ServiceException("添加错误，添加订单必填项输入不全");
            }

            //同时创建MemberCode
            DyMemberCode code = new DyMemberCode();
            code.setAnchorId(dyAnchorVo.getId());
            code.setAnchorName(dyAnchorVo.getName());
            code.setToken(IdUtil.simpleUUID());
            code.setPayType(0);
            code.setPayUrl(bo.getPayUrl());
            code.setRemark(bo.getRemark());
            code.setOrderNo(orderNo);
            code.setStatus(0L);
            dyMemberCodeMapper.insert(code);

            dyOrder.setToken(code.getToken());
            dyOrder.setType(bo.getPayType());
            dyOrder.setOrderStatus(1);
            dyOrder.setTradeNo(bo.getTradeNo());
            dyOrder.setCreateBy(LoginHelper.getLoginUser().getUsername());
            dyOrder.setUpdateBy(LoginHelper.getLoginUser().getUsername());

            log.info("微信订单返回：  {}", result);
        }
        else if (bo.getPayType() == 1L){
            try {
                result = AlipayTradeWapPayUtils.getAliPayResBody(orderNo, totalAmount.toString(), dyGoodsVo.getName());

            } catch (Exception e) {
                throw new ServiceException(e.getMessage());
            }
            log.info("支付宝订单返回：  {}", result);
        }
        else if (bo.getPayType() == 2L){
            try {
                result = HfuPayUtils.hFuPayByJs(HfuPayUtils.A_NATIVE, dyGoodsVo.getName(), totalAmount.toString(), orderNo, null);

                HfuOrderResultVo resultVo = JsonUtils.parseObject(result, HfuOrderResultVo.class);

                if (resultVo == null || StringUtils.isEmpty(resultVo.getPartyOrderId())){
                    throw new ServiceException("下单失败");
                }

                if (!"10000".equals(resultVo.getBankCode()) || !"00000100".equals(resultVo.getRespCode())){
                    throw new ServiceException("下单失败");
                }
                dyOrder.setTradeNo(resultVo.getPartyOrderId());

            }catch (Exception e){
                throw new ServiceException(e.getMessage());
            }
            log.info("汇付支付宝订单返回：  {}", result);
        }
        else if (bo.getPayType() == 3L){

            if (StringUtils.isEmpty(bo.getOpenId())){
                throw new ServiceException("openid为空");
            }

            try {
                result = HfuPayUtils.hFuPayByJs(HfuPayUtils.T_JSAPI, dyGoodsVo.getName(), totalAmount.toString(), orderNo, bo.getOpenId());

                HfuPayResultJsonWxVo jsonWxVo = JsonUtils.parseObject(result, HfuPayResultJsonWxVo.class);

                if (jsonWxVo == null || !"00000100".equals(jsonWxVo.getRespCode())){
                    throw new ServiceException("下单失败");
                }

                dyOrder.setTradeNo(jsonWxVo.getPartyOrderId());
                dyOrder.setOpenId(bo.getOpenId());

            }catch (Exception e){
                throw new ServiceException(e.getMessage());
            }
            log.info("汇付微信订单返回：  {}", result);
        }

        // 生成订单
        dyOrder.setOrderNo(orderNo);
        dyOrder.setAmount(dyGoodsVo.getAmount());
        dyOrder.setGoodsId(dyGoodsVo.getId());
        dyOrder.setGoodsName(dyGoodsVo.getName());
        dyOrder.setAnchorId(dyGoodsVo.getAnchorId());
        dyOrder.setCreateTime(new Date());
        dyOrder.setUpdateTime(new Date());
        baseMapper.insert(dyOrder);

        return result;
    }


    /**
     * 生成编号
     * @return
     */
    public String buildOrderNo(){
        String preStr = "DD";
        String dateStr = TimeUtil.getDateTimeForOrder();
        String preRedisKey = DAY_ORDER_PRE_KEY + "_" + dateStr;
        Integer orderNum =  RedisUtils.getCacheObject(preRedisKey);
        if (ObjectUtil.isNotEmpty(orderNum)){
            orderNum = orderNum + 1;
            log.info("buildOrderNo,hasKey,orderNum:{}",orderNum);
            RedisUtils.setCacheObject(preRedisKey, orderNum, Duration.ofDays(1));
        } else {
            int DAY_ORDER_NO_INIT = 10000000;
            orderNum = DAY_ORDER_NO_INIT;
            RedisUtils.setCacheObject(preRedisKey, DAY_ORDER_NO_INIT, Duration.ofDays(1));
            log.info("buildOrderNo,setCacheObject,preRedisKey:{}",preRedisKey);
        }
        String dayOrderNoStr = String.valueOf(orderNum);
        log.info("buildOrderNo,dayOrderNoStr:{}",dayOrderNoStr);
        String endStr = dayOrderNoStr.substring(1);
        log.info("buildOrderNo,endStr:{}",endStr);
        return preStr + dateStr + endStr;
    }


    @Override
    public String backOrderPay(String outTradeN, String tradeNo) {

        LambdaUpdateWrapper<DyOrder> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.set(DyOrder::getOrderStatus, OrderStatusEnum.PAID.getKey());
        lambdaUpdateWrapper.set(DyOrder::getUpdateBy, "order");
        lambdaUpdateWrapper.set(DyOrder::getUpdateTime, new Date());
        lambdaUpdateWrapper.set(DyOrder::getToken, IdUtil.simpleUUID());

        if (StringUtils.isNotEmpty(tradeNo)){
            lambdaUpdateWrapper.set(DyOrder::getTradeNo, tradeNo);
        }
        lambdaUpdateWrapper.eq(DyOrder::getOrderNo, outTradeN);
        int updateRes = baseMapper.update(null, lambdaUpdateWrapper);
        if (updateRes > 0){

            DyOrder order = baseMapper.selectOne(new QueryWrapper<DyOrder>().lambda().eq(DyOrder::getOrderNo, outTradeN));

            DyMemberCode code = new DyMemberCode();
            code.setStatus(0L);
            code.setTradeNo(tradeNo);
            code.setOrderNo(outTradeN);
            code.setAnchorId(order.getAnchorId());
            code.setAnchorName(order.getGoodsName());
            code.setPayUrl("");
            code.setToken(order.getToken());
            code.setPayType(1);
            code.setCreateBy("admin");
            code.setCreateTime(new Date());
            code.setUpdateBy("admin");
            code.setUpdateTime(new Date());
            dyMemberCodeMapper.insert(code);

            return AlipayConstants.alipayResponseSuccess;
        }
        return AlipayConstants.alipayResponseFail;
    }

    @Override
    public int refundOrder(DyOrderBo bo) {

        if (bo.getId() == null){
            throw new ServiceException("参数不全");
        }

        DyOrder order = baseMapper.selectById(bo.getId());

        //取消关联
        List<DyMemberCode> codes = dyMemberCodeMapper.selectList(new QueryWrapper<DyMemberCode>().lambda().eq(DyMemberCode::getOrderNo, order.getOrderNo()));
        if (CollUtil.isNotEmpty(codes)){
            for (DyMemberCode code : codes) {
                code.setStatus(1L);

                DyClientAnchor clientAnchor = dyClientAnchorMapper.selectOne(new QueryWrapper<DyClientAnchor>().lambda().eq(DyClientAnchor::getToken, code.getToken()));
                if (clientAnchor != null){
                    dyClientAnchorMapper.deleteById(clientAnchor);
                }
            }
            dyMemberCodeMapper.updateBatchById(codes);
        }

        order.setOrderStatus(2);
        return baseMapper.updateById(order);
    }

    @Override
    public int resetCode(DyOrderBo bo) {

        if (bo.getId() == null){
            throw new ServiceException("重置参数为空");
        }

        DyOrder order = baseMapper.selectById(bo.getId());
        if (order == null){
            throw new ServiceException("重置的订单为空");
        }

        DyMemberCode code = dyMemberCodeMapper.selectOne(new QueryWrapper<DyMemberCode>().lambda().eq(DyMemberCode::getOrderNo, order.getOrderNo()));

        if (code != null){

            List<DyClientAnchor> anchors = dyClientAnchorMapper.selectList(new QueryWrapper<DyClientAnchor>().lambda().eq(DyClientAnchor::getToken, code.getToken()));
            if (CollUtil.isNotEmpty(anchors)){
                List<Long> ids = anchors.stream().map(DyClientAnchor::getId).collect(Collectors.toList());
                dyClientAnchorMapper.deleteBatchIds(ids);
            }

            String token = IdUtil.simpleUUID();

            order.setToken(token);
            baseMapper.updateById(order);

            code.setToken(token);
            code.setStatus(0L);
            return dyMemberCodeMapper.updateById(code);
        }

        return 0;
    }

    @Override
    public DyOrderVo getOrderInfoByTradeNo(DyOrderBo bo) {

        if (StringUtils.isEmpty(bo.getTradeNo())){
            throw new ServiceException("查询的订单号不存在");
        }

        DyOrder dyOrder = baseMapper.selectOne(new LambdaQueryWrapper<DyOrder>().eq(DyOrder::getTradeNo, bo.getTradeNo()));

        return BeanUtil.toBean(dyOrder, DyOrderVo.class);
    }

    @Override
    public List<OrderIndexCompanySumVo> getIndexCompanySum(DyIndexBo bo) {
        List<OrderIndexCompanySumVo> result = new ArrayList<>();
        List<DyRemitRecordVo> remitRecordVos;
        LoginUser loginUser = bo.getLoginUser();
        if (loginUser == null){
            throw new ServiceException("未登录！");
        }

        List<SysDept> deptList = sysDeptMapper.selectList(
                new QueryWrapper<SysDept>().lambda().eq(SysDept::getParentId, 0).or().eq(SysDept::getParentId, 100));

        if (deptList.isEmpty()){
            return result;
        }

        if (loginUser.getDeptId() != 100){
            deptList = deptList.stream().filter(r -> Objects.equals(r.getDeptId(), loginUser.getDeptId())).collect(Collectors.toList());
        }

        BigDecimal otherNum = new BigDecimal(0);

        List<Long> deptIds = deptList.stream().map(SysDept::getDeptId).collect(Collectors.toList());

        LambdaQueryWrapper<DyRemitRecord> queryWrapperRemitRecord = new LambdaQueryWrapper<>();
        queryWrapperRemitRecord.in(DyRemitRecord::getCompanyId, deptIds);
        remitRecordVos = dyRemitRecordMapper.selectVoList(queryWrapperRemitRecord);

        Map<Long,Integer> companyRemitMap = new HashMap<>();
        if (CollectionUtil.isNotEmpty(remitRecordVos)){
            companyRemitMap = remitRecordVos.stream().collect(Collectors.groupingBy(DyRemitRecordVo::getCompanyId, Collectors.summingInt(DyRemitRecordVo::getAmount)));
        }

        for (SysDept sysDept : deptList) {
            OrderIndexCompanySumVo orderIndexCompanySumVo = new OrderIndexCompanySumVo();

            orderIndexCompanySumVo.setCompanyId(sysDept.getDeptId());
            orderIndexCompanySumVo.setCompanyName(sysDept.getDeptName());

            LambdaQueryWrapper<DyAnchor> queryWrapperAnchor = new LambdaQueryWrapper<>();
            queryWrapperAnchor.eq(DyAnchor::getCompanyId, sysDept.getDeptId());
            List<DyAnchorVo> anchorVos = dyAnchorMapper.selectVoList(queryWrapperAnchor);

            Map<Long,DyAnchorVo> anchorMap = anchorVos.stream().collect(Collectors.toMap(DyAnchorVo::getId,entity -> entity,(k1,k2) -> k1));

            BigDecimal incomeSum = new BigDecimal(0);

            if (ObjectUtil.isNotEmpty(companyRemitMap.get(sysDept.getDeptId()))){
                incomeSum = new BigDecimal(companyRemitMap.get(sysDept.getDeptId()));
                orderIndexCompanySumVo.setIncomeSum(incomeSum);
            }

            if (CollectionUtil.isNotEmpty(anchorVos)){
                List<Long> anchorIds = anchorVos.stream().map(DyAnchorVo::getId).collect(Collectors.toList());
                LambdaQueryWrapper<DyOrder> queryWrapperOrder = new LambdaQueryWrapper<>();
                queryWrapperOrder.in(DyOrder::getAnchorId, anchorIds);
                queryWrapperOrder.eq(DyOrder::getOrderStatus, 1);
                if (ObjectUtil.isNotEmpty(bo.getStartTimeStart()) && ObjectUtil.isNotEmpty(bo.getStartTimeEnd())){
                    queryWrapperOrder.between(DyOrder::getUpdateTime, bo.getStartTimeStart(), bo.getStartTimeEnd());
                }
                List<DyOrderVo> orderVos = baseMapper.selectVoList(queryWrapperOrder);

                BigDecimal companyIncome = new BigDecimal(0);
                for (DyOrderVo item : orderVos){
                    if (ObjectUtil.isNotEmpty(anchorMap.get(item.getAnchorId()))){
                        DyAnchorVo dyAnchorVo = anchorMap.get(item.getAnchorId());
                        BigDecimal companyPoint = BigDecimal.valueOf(dyAnchorVo.getCompanyPoint());
                        BigDecimal point = companyPoint.divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);
                        BigDecimal companyIncomeItem = point.multiply(BigDecimal.valueOf(item.getAmount()));
                        companyIncome = companyIncome.add(companyIncomeItem);

                        if (sysDept.getParentId() == 100){
                            BigDecimal sum = companyIncomeItem.divide(point, 0, RoundingMode.HALF_UP);
                            otherNum = otherNum.add(sum.multiply(new BigDecimal(1).subtract(point)));
                        }

                    }
                }

                // 计算已打款
                if (ObjectUtil.isNotEmpty(companyRemitMap.get(sysDept.getDeptId()))){
                    BigDecimal unIncomeSum = companyIncome.subtract(incomeSum);
                    orderIndexCompanySumVo.setUnIncomeSum(unIncomeSum);
                } else {
                    orderIndexCompanySumVo.setUnIncomeSum(companyIncome);
                }
                orderIndexCompanySumVo.setTotalSum(companyIncome);
            }

            result.add(orderIndexCompanySumVo);
        }

        for (OrderIndexCompanySumVo orderIndexCompanySumVo : result) {
            if (orderIndexCompanySumVo.getCompanyId() == 100L){
                orderIndexCompanySumVo.setTotalSum(orderIndexCompanySumVo.getTotalSum().add(otherNum));
            }
        }

        return result;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(DyOrder entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除订单
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }


    @Override
    public String hfuPayResult(HttpServletRequest request) {

        Map<String, String[]> map = request.getParameterMap();

        log.info("hf result : =========  {} ", JsonUtils.toJsonString(map));

        //验签
        if (map != null){

            HfuPayResultJsonVo jsonVo = BeanUtil.toBean(map, HfuPayResultJsonVo.class);

            String sign = jsonVo.getSign().get(0);
            String data = jsonVo.getRespData().get(0);

            if (!RsaUtils.verify(data, HfuPayConfig.getMerchantConfig().getRsaPublicKey(), sign)) {
                // 验签失败处理
                log.error("======================== 汇付验签失败 ========================");
                return "";
            }

            String reqSeqId = "";

            String code = jsonVo.getRespCode().get(0);
            if ("00000000".equals(code)){

                log.info("======================== 汇付回调状态为 {} ========================", code);

                HfuPayResultJsonVo.respDataDetail detail = JsonUtils.parseObject(data, HfuPayResultJsonVo.respDataDetail.class);
                log.info("======================== data 数据为 {} ========================", detail);

                reqSeqId = detail.getReqSeqId();

                //判断是否支付成功
                if (!"00000000".equals(detail.getRespCode())){
                    return "";
                }

                //修改订单支付状态
                String partyOrderId = detail.getPartyOrderId();
                DyOrder order = baseMapper.selectOne(new LambdaQueryWrapper<DyOrder>().eq(DyOrder::getTradeNo, partyOrderId));

                if(order != null){

                    order.setOrderStatus(1);
                    order.setToken(IdUtil.simpleUUID());
                    order.setUpdateTime(new Date());
                    order.setUpdateBy("admin");
                    baseMapper.updateById(order);

                    log.info("======================== 汇付回调订单修改完毕 {} ========================", order.getId());

                    //保存用户code
                    DyMemberCode memberCode = new DyMemberCode();
                    memberCode.setStatus(1L);
                    memberCode.setTradeNo(order.getTradeNo());
                    memberCode.setOrderNo(order.getOrderNo());
                    memberCode.setAnchorId(order.getAnchorId());
                    memberCode.setAnchorName(order.getGoodsName());
                    memberCode.setPayUrl("");
                    memberCode.setToken(order.getToken());
                    memberCode.setPayType(order.getType().intValue());
                    memberCode.setCreateBy("admin");
                    memberCode.setCreateTime(new Date());
                    memberCode.setUpdateBy("admin");
                    memberCode.setUpdateTime(new Date());
                    dyMemberCodeMapper.insert(memberCode);

                    DyClient client = dyClientMapper.selectOne(new LambdaQueryWrapper<DyClient>().eq(DyClient::getOpenId, order.getOpenId()));


                    if (client != null && order.getType() == 3L){

                        DyClientAnchor anchor = dyClientAnchorMapper.selectOne(new LambdaQueryWrapper<DyClientAnchor>().eq(DyClientAnchor::getClientId, client.getId()).eq(DyClientAnchor::getAnchorId, order.getAnchorId()));

                        if (anchor == null){
                            //直接绑定
                            DyClientAnchor dyClientAnchor = new DyClientAnchor();
                            dyClientAnchor.setAnchorId(order.getAnchorId());
                            dyClientAnchor.setAnchorName(order.getGoodsName());
                            dyClientAnchor.setClientId(client.getId());
                            dyClientAnchor.setToken(memberCode.getToken());
                            dyClientAnchor.setBuyType(0);

                            DyAnchorPhoto photo = dyAnchorPhotoMapper.selectOne(new LambdaQueryWrapper<DyAnchorPhoto>().eq(DyAnchorPhoto::getId, order.getAnchorId()).orderByDesc(DyAnchorPhoto::getNewestTime).last(" limit 1"));

                            if (photo != null){
                                dyClientAnchor.setNewestTime(photo.getNewestTime());
                            }

                            dyClientAnchor.setCreateBy("admin");
                            dyClientAnchor.setCreateTime(new Date());
                            dyClientAnchor.setUpdateBy("admin");
                            dyClientAnchor.setUpdateTime(new Date());
                            dyClientAnchorMapper.insert(dyClientAnchor);
                        }
                    }
                }
            }
            else {
                return "";
            }

            return "RECV_ORD_ID_" + reqSeqId;
        }

        return "";
    }

    @Override
    public String getHfuPayStatus(HfuPayResultVo hfuPayResultVo) {

        String result = "";

        if (StringUtils.isNotEmpty(hfuPayResultVo.getPartyOrderId())){
            try {
                result =  HfuPayUtils.hfuPayStatus(hfuPayResultVo.getPartyOrderId(), hfuPayResultVo.getTradeType(), hfuPayResultVo.getOpenId());
            } catch (Exception e) {
                throw new ServiceException(e.getMessage());
            }
        }

        return result;
    }

    @Override
    public int complaintOrder(DyOrderBo bo) {

        if (bo.getId() == null && bo.getComplaint() == null){
            throw new ServiceException("参数不全");
        }

        DyOrder order = baseMapper.selectById(bo.getId());

        order.setComplaint(bo.getComplaint());
        order.setComplaintReason(bo.getComplaintReason());
        return baseMapper.updateById(order);
    }

}
